package com.chiyoyo.rabbitmq.framework.dto;

import cn.hutool.core.util.ObjectUtil;
import com.chiyoyo.rabbitmq.framework.annotation.RabbitMq;
import com.chiyoyo.rabbitmq.framework.utils.SpringUtil;
import lombok.Getter;
import lombok.Setter;

import java.util.HashMap;
import java.util.Map;

/**
 * @author chil
 */
@Setter
@Getter
public class InitRabbitBinding {
    /**
     * 队列名
     */
    String queue;
    /**
     * 交换器名
     */
    String exchange;
    /**
     * 路由键名
     */
    String routingKey;

    Map<String, Object> args;

    /**
     * 初始化RabbitBinding对象
     *
     * @param rabbitMq       RabbitMq对象
     * @param queueName      队列名
     * @param isInitDlxMap   是否初始化DLX映射
     * @param isAddDlxPrefix 是否添加DLX前缀
     */
    public InitRabbitBinding(RabbitMq rabbitMq, String queueName, boolean isInitDlxMap, boolean isAddDlxPrefix) {
        // 队列名
        this.queue = this.getName(queueName, isAddDlxPrefix);
        // 交换机名
        this.exchange = this.getName(rabbitMq.exchange(), isAddDlxPrefix);
        // 路由
        this.routingKey = this.getName(rabbitMq.routingKey(), isAddDlxPrefix);
        this.args = this.initArgs(rabbitMq, isInitDlxMap);
    }

    /**
     * 获取队列名或交换机名或路由键名
     *
     * @param name           队列名或交换机名或路由键名
     * @param isAddDlxPrefix 是否添加DLX前缀
     * @return 队列名或交换机名或路由键名，如果name为空则返回空字符串；如果isAddDlxPrefix为true，则在name前添加DLX前缀
     */
    private String getName(String name, boolean isAddDlxPrefix) {
        if (name == null || name.isEmpty()) {
            return name;
        }
        name = SpringUtil.getElValue(name, SpringUtil.getElDefaultValue(name));
        return isAddDlxPrefix ? BaseRabbitMqConstant.DLX_PREFIX + name : name;
    }

    /**
     * 绑定死信队列参数
     *
     * @param rabbitMq     MQ注解
     * @param isInitDlxMap 是否初始化死信队列参数
     * @return 死信队列参数
     */
    private Map<String, Object> initArgs(RabbitMq rabbitMq, boolean isInitDlxMap) {
        boolean dlx = !void.class.equals(rabbitMq.dlxClazz()) || rabbitMq.delay() != 0L;
        Map<String, Object> args = new HashMap<>(3);
        if (!dlx || !isInitDlxMap) {
            return args;
        }
        args.put(BaseRabbitMqConstant.DLX_EXCHANGE_KEY, BaseRabbitMqConstant.DLX_PREFIX + rabbitMq.exchange());

        if (ObjectUtil.isNotEmpty(rabbitMq.routingKey())) {
            args.put(BaseRabbitMqConstant.DLX_ROUTING_KEY, BaseRabbitMqConstant.DLX_PREFIX + rabbitMq.routingKey());
        }
        /*
         * x-message-ttl 在创建队列时设置的消息TTL，表示消息在队列中最多能存活多久（ms）；
         * Expiration 发布消息时设置的消息TTL，消息自产生后的存活时间（ms）；
         * x-delay 由rabbitmq_delayed_message_exchange插件提供TTL，从交换机延迟投递到队列的时间（ms）；
         */
        if (rabbitMq.delay() != 0L && !rabbitMq.isDelayExchange()) {
            args.put(BaseRabbitMqConstant.DLX_TTL, rabbitMq.delay());
        }
        return args;
    }
}
